/*
 * {comment of class}
 *
 * @author (C) <a href="http://www.carfield.com.hk">Carfield Yim</a>, 2005
 */
package hk.com.carfield.core;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;

import hk.com.carfield.action.Body;
import hk.com.carfield.core.Config;
import hk.com.carfield.util.FileUtil;
import hk.com.carfield.util.TemplateUtil;
import hk.com.carfield.util.UrlUtil;
import hk.com.carfield.web.Request;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.io.VelocityWriter;
import org.apache.velocity.util.SimplePool;

public final class TemplateManager {
	final private VelocityEngine ve = new VelocityEngine();
	public TemplateManager() {
		ve.setProperty("resource.loader", "class");
		ve.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
		ve.setProperty("runtime.log.logsystem.class", "org.apache.velocity.runtime.log.NullLogSystem");
		try {
			ve.init();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	private VelocityContext getContext(final Context context, final Body body, final File location, final Request request) throws IOException {
		final Config config = context.config;
        final VelocityContext ctx = new VelocityContext();
		ctx.put("body", body);
		ctx.put("util", new TemplateUtil());
		ctx.put("session", request);
		ctx.put("ancestor", FileUtil.getParents(context, location, request));
		ctx.put("encodedpath", UrlUtil.getEncodedPath(config, location));
		ctx.put("children", FileUtil.getChildred(context, location, request));
		return ctx;
	}
	
	public void mergeTemplate(final Context context, final Body body, final File location, final Request request, final String encoding, final OutputStream output) throws Exception {
		final Template template = ve.getTemplate("hk/com/carfield/web/template.vm", "UTF-8");
		final VelocityContext vc = getContext(context, body, location, request);
		VelocityWriter vw = null;
		try {
			vw = (VelocityWriter) writerPool.get();
			if (vw == null)
				vw = new VelocityWriter(new OutputStreamWriter(output, encoding), 4096, true);
			else
				vw.recycle(new OutputStreamWriter(output, encoding));

			template.merge(vc, vw);

        } catch(java.net.SocketException e) {
            // ignore socket exception like Broken pipe
		} finally {
			try {
				if (vw != null) {
					vw.flush();
					vw.recycle(null);
					writerPool.put(vw);
				}
			} catch (Exception e) {
                // ignore exception if the vw cannot be recycled
			}
		}
	}
	private static SimplePool writerPool = new SimplePool(40);
}